﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using XChip_Common;

public class ParsedData
{
    public uint address { get; set; }
    public List<uint> values { get; set; }
    public byte[] fdbuf { get; set; }
    public byte[] febuf { get; set; }
    //新增crc校验
    public byte[] crc { get; set; }
}

public class I2CManager
{
    private uint mIndex; // USBIO 设备索引
    private const int SegmentSize = 2048; // 分段大小
    const uint StartAddr = 0x80b00ffc; // 起始地址
    const uint StartBddr = 0x80b02000; // 第二个起始地址

    // 定义委托类型
    public delegate void IndexCallback(int index);

    // 定义事件
    public event IndexCallback OnIndexProcessed;


    // 定义委托类型
    public delegate void MsgCallback(string Msg);

    // 定义事件
    public event MsgCallback OnMsgProcessed;

    public I2CManager(uint usbIndex)
    {
        mIndex = usbIndex;
    }

    /// <summary>
    /// 发送 I2C 数据
    /// </summary>
    /// <param name="subB">用于构建 I2C 数据的参数</param>
    /// <param name="data">要发送的数据</param>
    /// <param name="deviceNo">设备编号</param>
    /// <returns>成功发送返回 true，失败返回 false</returns>
    public bool SendI2CData(uint subB, List<uint> data, byte deviceNo)
    {
        if (subB > 0xFFFFFFFF)
        {
            return false; // 超过范围
        }

        if (subB <= 0xFFFF)
        {
            byte[] wbuffer = new byte[4];
            wbuffer[0] = deviceNo;
            wbuffer[1] = Convert.ToByte((subB >> 8) & 0xff);
            wbuffer[2] = Convert.ToByte(subB & 0xff);

            if (data.Count > 0)
            {
                wbuffer[3] = Convert.ToByte(data[0]);
            }
            else
            {
                return false;
            }

            return USBIOXdll.USBIO_StreamI2C(mIndex, Convert.ToUInt16(wbuffer.Length), wbuffer, 0, null);
        }

        if (!SendI2CSubBByte(deviceNo, (byte)((subB >> 24) & 0xff), 0xfd))
        {
            return false;
        }

        if (!SendI2CSubBByte(deviceNo, (byte)((subB >> 16) & 0xff), 0xfe))
        {
            return false;
        }

        byte[] wbufferFinal = new byte[3 + data.Count];
        wbufferFinal[0] = deviceNo;
        wbufferFinal[1] = Convert.ToByte((subB >> 8) & 0xff);
        wbufferFinal[2] = Convert.ToByte(subB & 0xff);

        for (int i = 0; i < data.Count; i++)
        {
            wbufferFinal[3 + i] = Convert.ToByte(data[i]);
        }

        return USBIOXdll.USBIO_StreamI2C(mIndex, Convert.ToUInt16(wbufferFinal.Length), wbufferFinal, 0, null);
    }

    /// <summary>
    /// 获取 I2C 数据
    /// </summary>
    /// <param name="subB">用于构建 I2C 数据的参数</param>
    /// <param name="deviceNo">设备编号</param>
    /// <param name="readLength">要读取的数据长度</param>
    /// <param name="readData">输出读取的数据</param>
    /// <returns>成功获取返回 true，失败返回 false</returns>
    public bool GetI2CData(uint subB, byte deviceNo, int readLength, out byte[] readData)
    {
        readData = null;



        if (readLength <= 0)
        {
            return false;
        }

        if (subB <= 0xFFFF)
        {
            byte[] wbuffer = new byte[3];
            byte[] rbuffer = new byte[readLength];

            wbuffer[0] = deviceNo;
            wbuffer[1] = Convert.ToByte((subB >> 8) & 0xff);
            wbuffer[2] = Convert.ToByte(subB & 0xff);

            if (USBIOXdll.USBIO_StreamI2C(mIndex, Convert.ToUInt32(wbuffer.Length), wbuffer, Convert.ToUInt32(rbuffer.Length), rbuffer))
            {
                readData = rbuffer;
                return true;
            }
            else
            {
                return false;
            }
        }

        if (!SendI2CSubBByte(deviceNo, (byte)((subB >> 24) & 0xff), 0xfd))
        {
            return false;
        }

        if (!SendI2CSubBByte(deviceNo, (byte)((subB >> 16) & 0xff), 0xfe))
        {
            return false;
        }

        byte[] wbuffer32 = new byte[3];
        byte[] rbuffer32 = new byte[readLength];

        wbuffer32[0] = deviceNo;
        wbuffer32[1] = Convert.ToByte((subB >> 8) & 0xff);
        wbuffer32[2] = Convert.ToByte(subB & 0xff);

        if (USBIOXdll.USBIO_StreamI2C(mIndex, Convert.ToUInt32(wbuffer32.Length), wbuffer32, Convert.ToUInt32(rbuffer32.Length), rbuffer32))
        {
            readData = rbuffer32;
            return true;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// 发送 I2C 子字节
    /// </summary>
    private bool SendI2CSubBByte(byte deviceNo, byte dataByte, byte controlByte)
    {
        byte[] fdbuf = new byte[4]
        {
            deviceNo,
            0xff,
            controlByte,
            dataByte
        };

        return USBIOXdll.USBIO_StreamI2C(mIndex, Convert.ToUInt16(fdbuf.Length), fdbuf, 0, null);
    }



    bool IsShow = true;
    // <summary>
    /// 解析文本文件
    /// </summary>
    public List<ParsedData> ParseAddresses(string filePath)
    {
        string fileContent = File.ReadAllText(filePath);
        var result = new List<ParsedData>();

        // 获取桌面路径
        string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
        // 定义输出文件路径
        string outputPath = Path.Combine(desktopPath, "ParsedAddresses.txt");


        var lines = fileContent.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
        foreach (var line in lines)
        {
            var match = System.Text.RegularExpressions.Regex.Match(line.Trim(), @"^(0x[0-9A-Fa-f]+)(?:, \{(.+?)\}|, (.+?))?$");
            if (match.Success)
            {
                string address = match.Groups[1].Value;
                uint addr = Convert.ToUInt32(address, 16);
                string values = match.Groups[2].Value;

                var valueList = new List<uint>();
                foreach (var value in values.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (uint.TryParse(value.Trim().Replace("0x", ""), System.Globalization.NumberStyles.HexNumber, null, out uint parsedValue))
                    {
                        valueList.Add(parsedValue);
                    }
                }

                if (address.Contains("20007e00") && IsShow)
                {
                    using (var writer = new StreamWriter(outputPath, false)) // true 表示追加写入
                    {
                        uint addr7e = 0x7e00;
                        foreach (var item in valueList)
                        {
                            writer.WriteLine($"0x{addr7e:X4},0x{item.ToString("X2")},");
                            addr7e++;
                        }

                        writer.WriteLine(); // 添加空行，增加可读性
                    }

                }
                int valNo = (int)Math.Ceiling((double)valueList.Count / SegmentSize);
                for (int i = 0; i < valNo; i++)
                {
                    var segmentValues = valueList.Skip(i * SegmentSize).Take(SegmentSize).ToList();
                    var addrTemp = addr + (uint)(i * SegmentSize);

                    ParsedData parsedData = new ParsedData
                    {
                        address = addrTemp,
                        values = segmentValues,
                        fdbuf = new byte[4] { 0x00, 0xff, 0xfd, (byte)((addrTemp >> 24) & 0xff) },
                        febuf = new byte[4] { 0x00, 0xff, 0xfd, (byte)((addrTemp >> 16) & 0xff) }
                    };

                    result.Add(parsedData);
                }
            }
        }


        return result;
    }

    /// <summary>
    /// 解析二进制文件
    /// </summary>
    public List<ParsedData> ParseBinAddresses(string filePath)
    {
        // 创建结果列表，用于存储解析后的数据块
        var result = new List<ParsedData>();

        // 使用FileStream打开二进制文件（只读模式）
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            // 创建4KB读取缓冲区
            byte[] buffer = new byte[4096];
            int bytesRead;  // 实际读取的字节数
            uint currentAddress = 0;  // 当前数据块的起始地址

            // 循环读取文件直到结束（每次最多读取4KB）
            while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
            {
                // 创建当前数据块的解析对象
                ParsedData data = new ParsedData
                {
                    address = currentAddress,
                    values = new List<uint>(),

                    fdbuf = new byte[4] {
                    0x00,
                    0xff,
                    0xfd,
                    (byte)((currentAddress >> 24) & 0xff)
                },

                    febuf = new byte[4] {
                    0x00,
                    0xff,
                    0xfe,
                    (byte)((currentAddress >> 16) & 0xff)
                }
                };

                // 将实际读取的字节添加到values列表
                for (int i = 0; i < bytesRead; i++)
                {
                    data.values.Add(buffer[i]);  // 存储每个字节（自动转换为uint）
                }

                // 新增 创建仅包含有效数据的数组（避免缓冲区末尾的无效数据）
                byte[] validData = new byte[bytesRead];
                Array.Copy(buffer, 0, validData, 0, bytesRead);

                // 新增 计算有效数据的CRC16校验值（初始值0xFFFF）
                ushort crc = XchipCrcCheck16(0xFFFF, validData);

                // 新增 存储CRC值（小端序：低字节在前，高字节在后）
                data.crc = new byte[2];
                data.crc[0] = (byte)(crc & 0xFF);        // CRC低字节
                data.crc[1] = (byte)((crc >> 8) & 0xFF);  // CRC高字节

                result.Add(data);

                // 更新下一个数据块的起始地址（按实际读取字节数递增）
                currentAddress += (uint)bytesRead;
            }
        }
        return result;
    }

    public bool _isCancelled = false;

    public bool _isDebug = true;


    // 为A区（偶数索引）和B区（奇数索引）分别保存上一次发送的数据块
    private ParsedData _prevBufferAData = null;
    private ParsedData _prevBufferBData = null;



    public void SendDataToBuffers(List<ParsedData> parsedDataList, byte deviceNo)
    {

        _isCancelled = false;


        try
        {
            // 初始化检查
            //if (!IsDevicePresent(deviceNo)) return;
            //新增烧录功能patch是否运行正常标记位:0x58表示运行正常
            byte[] readData = new byte[1];
            if (GetI2CData(0x200014cb, deviceNo, 1, out readData) && readData[0] != 0x58 || _isCancelled) return;


            // 发送初始数据
            if (!SendI2CData(0x80251000, new List<uint> { 0x1 }, deviceNo) || _isCancelled) return;
            // 0x20006e31 // 烧录使能地址  设置状态为 0xE1(使能)，0x8E(取消使能)。
            if (!SendI2CData(0x20006e31, new List<uint> { 0xE1 }, deviceNo) || _isCancelled) return;


            //● 0x20006e32 // Flash读取标志 设置状态为0xD2(需要读)，0x7D(可以读)。
            //if (!SendI2CData(0x20006e32, new List<uint> { 0xD2 }, deviceNo) || _isCancelled) return;


            StringBuilder msg = new StringBuilder();
            if (_isDebug && !_isCancelled)
            {
                byte[] readData0, readData1, readData2, readData3, readData4;
                //GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
                //msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
                GetI2CData(0x20006df0, deviceNo, 1, out readData0);
                GetI2CData(0x20006df1, deviceNo, 1, out readData1);
                GetI2CData(0x20006df2, deviceNo, 1, out readData2);
                GetI2CData(0x20006df3, deviceNo, 1, out readData3);
                GetI2CData(0x20006df4, deviceNo, 1, out readData4);
                msg.AppendLine($"0x{0x20006df0:X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},0x{readData4[0]:X},");
                msg.AppendLine("");
                GetI2CData(0x8050000e, deviceNo, 1, out readData3);
                GetI2CData(0x2000000c, deviceNo, 1, out readData4);
                msg.AppendLine($"0x{0x8050000e:X},0x{readData3[0]:X},0x{0x2000000c:X},0x{readData4[0]:X},");

                OnMsgProcessed?.Invoke(msg.ToString());

            }

            // 主循环处理固件数据
            for (int i = 0; i < parsedDataList.Count && !_isCancelled; i++)
            {
                if (_isCancelled) break;

                if (i % 2 == 0) // A区处理（偶数索引）
                {
                    SendDataToBuffer(
                        parsedData: parsedDataList[i],          // 当前数据块
                        lastSentData: _prevBufferAData,         // 上一次A区发送的数据
                        startAddress: StartAddr,                // 数据写入起始地址
                        deviceNo: deviceNo,                     // I2C设备编号

                        // 缓冲区1专用硬件寄存器地址
                        waitFlagAddress: 0x20006e33,            // 等待标志地址
                        crcErrorAddress: 0x20006e35,            // CRC错误标志地址
                        spiErrorAddress: 0x20006e37,            // SPI错误标志地址
                        crcWriteAddress: 0x20001344,            // CRC写入地址
                        startAddressCommand: 0x80b00ff8,        // 起始地址命令寄存器

                        // 缓冲区1专用状态值
                        expectedReady: 0x6C,                    // 就绪期望值
                        triggerValue: 0xC3,                     // 缓冲区处理写触发值
                        crcReady: 0xA9,                         // CRC正常状态值
                        spiReady: 0x56,                         // SPI正常状态值
                        bufferType: 0                           // 0 = A区
                    );

                    // 更新A区上一次数据块
                    _prevBufferAData = parsedDataList[i];
                }
                else // B区处理（奇数索引）
                {
                    SendDataToBuffer(
                        parsedData: parsedDataList[i],          // 当前数据块
                        lastSentData: _prevBufferBData,         // 上一次B区发送的数据
                        startAddress: StartBddr,                // 数据写入起始地址
                        deviceNo: deviceNo,                     // I2C设备编号

                        // 缓冲区2专用硬件寄存器地址
                        waitFlagAddress: 0x20006e34,            // 等待标志地址
                        crcErrorAddress: 0x20006e36,            // CRC错误标志地址
                        spiErrorAddress: 0x20006e37,            // SPI错误标志地址
                        crcWriteAddress: 0x20001346,            // CRC写入地址
                        startAddressCommand: 0x80b01ffc,        // 起始地址命令寄存器

                        // 缓冲区2专用状态值
                        expectedReady: 0x5B,                    // 就绪期望值
                        triggerValue: 0xB4,                     // 缓冲区处理写触发值
                        crcReady: 0x87,                         // CRC正常状态值
                        spiReady: 0x56,                         // SPI正常状态值
                        bufferType: 1                           // 1 = B区
                    );

                    // 更新B区上一次数据块
                    _prevBufferBData = parsedDataList[i];
                }

                // 通知进度更新
                OnIndexProcessed?.Invoke(i);
            }

            // 调试信息输出
            if (_isDebug && !_isCancelled)
            {

                byte[] readData0, readData1, readData2, readData3, readData4;

                // 读取调试寄存器
                GetI2CData(0x20006df0, deviceNo, 1, out readData0);
                GetI2CData(0x20006df1, deviceNo, 1, out readData1);
                GetI2CData(0x20006df2, deviceNo, 1, out readData2);
                GetI2CData(0x20006df3, deviceNo, 1, out readData3);
                GetI2CData(0x20006df4, deviceNo, 1, out readData4);

                msg.AppendLine($"------>  0x{0x20006df0:X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},0x{readData4[0]:X},");
                msg.AppendLine("");

                // 读取更多调试寄存器
                GetI2CData(0x8050000e, deviceNo, 1, out readData3);
                GetI2CData(0x2000000c, deviceNo, 1, out readData4);
                msg.AppendLine($"0x{0x8050000e:X},0x{readData3[0]:X},0x{0x2000000c:X},0x{readData4[0]:X},");

                OnMsgProcessed?.Invoke(msg.ToString());
            }
        }
        finally
        {
            // 最终清理操作
            SendI2CData(0x20006e31, new List<uint> { 0x8E }, deviceNo);
        }




        //// 发送初始数据
        //SendI2CData(0x80251000, new List<uint> { 0x1 }, deviceNo);
        //SendI2CData(0x80b00fec, new List<uint> { 0x1 }, deviceNo);
        //StringBuilder msg = new StringBuilder();
        //msg.AppendLine($"------------- 分割线  --------");
        //byte[] readData0, readData1, readData2, readData3, readData4;
        ////GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
        ////msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
        //GetI2CData(0x20006df0, deviceNo, 1, out readData0);
        //GetI2CData(0x20006df1, deviceNo, 1, out readData1);
        //GetI2CData(0x20006df2, deviceNo, 1, out readData2);
        //GetI2CData(0x20006df3, deviceNo, 1, out readData3);
        //GetI2CData(0x20006df4, deviceNo, 1, out readData4);
        //msg.AppendLine($"0x{0x20006df0:X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},0x{readData4[0]:X},");

        //OnMsgProcessed?.Invoke(msg.ToString());

        //for (int i = 0; i < parsedDataList.Count; i++)
        //{
        //    if (_isCancelled) break;
        //    if (i % 2 == 0)
        //        {
        //            SendDataToBuffer(parsedDataList[i], StartAddr, deviceNo, 0x80b00fee, 0x80b00ff0, 0x80b00ff8);
        //        }
        //        else
        //        {
        //            SendDataToBuffer(parsedDataList[i], StartBddr, deviceNo, 0x80b00fef, 0x80b00ff1, 0x80b01ffc);
        //        }



        //    // 触发委托事件
        //    OnIndexProcessed?.Invoke(i); // 触发事件，传递当前索引
        //}
        ////GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
        ////msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
        //GetI2CData(0x20006df0, deviceNo, 1, out readData0);
        //GetI2CData(0x20006df1, deviceNo, 1, out readData1);
        //GetI2CData(0x20006df2, deviceNo, 1, out readData2);
        //GetI2CData(0x20006df3, deviceNo, 1, out readData3);
        //GetI2CData(0x20006df4, deviceNo, 1, out readData4);
        //msg.AppendLine($"------>  0x{0x20006df0 :X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},0x{readData4[0]:X},");

        //OnMsgProcessed?.Invoke(msg.ToString());


        //SendI2CData(0x80b00fec, new List<uint> { 0x0 }, deviceNo); // 结束时重置状态
    }

    //public string msg = string.Empty;
    public void SendDataToBuffer(ParsedData parsedData, uint startAddress, byte deviceNo, uint waitFlagAddress, uint errorFlagAddress, uint startAddressCommand)
    {
        // 等待缓冲区准备状态
        if (!WaitForBufferReady(waitFlagAddress, deviceNo)) { return; }

        // 发送缓冲区的起始地址
        // 3. 发送缓冲区的起始地址（带取消检查）
        if (_isCancelled || !SendI2CData(startAddressCommand, GetAddressData(parsedData.address), deviceNo))
        {
            return;
        }
        //新增缓冲区的IIC CRC错误标志

        // SPI错误标志

        // 检查缓冲区等待标志
        if (!WaitForBufferReady(waitFlagAddress, deviceNo)) { return; }

        // 发送数据包
        //int totalPackets = (int)Math.Ceiling((double)parsedData.values.Count / SegmentSize);
        //SendPackets(parsedData, startAddress, deviceNo, totalPackets);
        if (!SendPacketsWithCheck(parsedData, startAddress, deviceNo))
        {
            return;
        }

        //新增发送crc
        // 缓冲区1使用0x20001344, 缓冲区2使用0x20001346
        uint crcAddress = (uint)((waitFlagAddress == 0x20006e33) ? 0x20001344 : 0x20001346);
        if (!SendI2CData(crcAddress, new List<uint> { parsedData.crc[0], parsedData.crc[1] }, deviceNo))
        {
            return;
        }


        //硬件处理时间100毫秒左右
        Thread.Sleep(300);



        StringBuilder msg = new StringBuilder();
        msg.AppendLine($"------------- 分割线  --------");
        byte[] readData;

        if (_isDebug && !_isCancelled)
        {
            // 发送等待标志，表示数据已准备好
            SendI2CData(waitFlagAddress, new List<uint> { 0x1 }, deviceNo);
            //硬件处理时间100毫秒左右
            Thread.Sleep(10);
            GetI2CData(waitFlagAddress, deviceNo, 1, out readData);
            msg.AppendLine($"{waitFlagAddress:x},{readData[0]:X},");
        }

        //硬件处理时间100毫秒左右
        Thread.Sleep(150);
        // 等待数据处理完成
        if (!WaitForDataProcessingCompletion(waitFlagAddress, deviceNo)) return;

        if (_isDebug && !_isCancelled)
        {
            //GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
            //msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
            byte[] readData0, readData1, readData2, readData3;
            //GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
            //msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
            GetI2CData(startAddressCommand + 4, deviceNo, 1, out readData0);
            GetI2CData(startAddressCommand + 5, deviceNo, 1, out readData1);
            GetI2CData(startAddressCommand + 6, deviceNo, 1, out readData2);
            GetI2CData(startAddressCommand + 7, deviceNo, 1, out readData3);
            msg.AppendLine($"0x{startAddressCommand + 4:X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},");


            SendI2CData(0x80b00ff2, new List<uint> { (0x1000 >> 8) & 0xff, 0x00 }, deviceNo);
            msg.AppendLine($"-->0x80b00ff2,{Convert.ToUInt16(parsedData.values.Count).ToString("X") },");


            SendI2CData(0x80b00ff4, GetAddressData(parsedData.address), deviceNo);
            msg.AppendLine($"-->0x80b00ff4,{parsedData.address:X},");
            SendI2CData(0x80b00fed, new List<uint> { 0x1 }, deviceNo);
            msg.AppendLine($"-->0x80b00fed,0x1 ,");
            do
            {
                Thread.Sleep(10);

            } while (GetI2CData(0x80b00fed, deviceNo, 1, out readData) && readData[0] != 0);
            //GetI2CData(0x80b00ffc, deviceNo, 1, out readData);
            //msg.AppendLine($"0x80b00ffc,{readData[0]:X},");
            GetI2CData(0x80b00ffc, deviceNo, 1, out readData0);
            GetI2CData(0x80b00ffd, deviceNo, 1, out readData1);
            GetI2CData(0x80b00ffe, deviceNo, 1, out readData2);
            GetI2CData(0x80b00fff, deviceNo, 1, out readData3);
            msg.AppendLine($"0x{startAddressCommand + 4:X},0x{readData0[0]:X},0x{readData1[0]:X},0x{readData2[0]:X},0x{readData3[0]:X},");


            GetI2CData(errorFlagAddress, deviceNo, 1, out readData);
            msg.AppendLine($"{errorFlagAddress:X},{readData[0]:X},");

            OnMsgProcessed?.Invoke(msg.ToString());
        }


        // 检查错误和等待标志
        if (!_isCancelled && CheckErrorAndWait(errorFlagAddress, deviceNo, maxRetries: 5))
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine($"检查错误和等待标志");
            // 发送缓冲区的起始地址
            SendI2CData(startAddressCommand, GetAddressData(parsedData.address), deviceNo);
            sb.AppendLine($"{startAddressCommand:X}{parsedData.address:X}");
            // 如果重试达到最大次数，进行重发
            SendPacketsWithCheck(parsedData, startAddress, deviceNo);
            //SendPackets(parsedData, startAddress, deviceNo, totalPackets);
            //sb.AppendLine($"{startAddress:X)}{Math.Ceiling((double)parsedData.values.Count / SegmentSize):X}");

            SendI2CData(errorFlagAddress, new List<uint> { 0x0 }, deviceNo);
            Thread.Sleep(300);
            SendI2CData(waitFlagAddress, new List<uint> { 0x1 }, deviceNo);
            //硬件处理时间100毫秒左右
            Thread.Sleep(200);
            OnMsgProcessed?.Invoke(sb.ToString());

        }


    }






    // 发送数据包的辅助方法
    private void SendPackets(ParsedData parsedData, uint startAddress, byte deviceNo, int totalPackets)
    {
        for (int j = 0; j < totalPackets; j++)
        {
            var data = parsedData.values.Skip(j * SegmentSize).Take(SegmentSize).ToList();
            SendI2CData(startAddress + (uint)(j * SegmentSize), data, deviceNo);
        }
    }
    // 带取消检查的数据包发送


    // 检查错误和等待标志的方法
    private bool CheckErrorAndWait(uint errorFlagAddress, byte deviceNo, int maxRetries = 5)
    {
        byte[] readData;

        int retryCount = 0;

        while (retryCount < maxRetries)
        {
            // 获取错误标志数据
            bool hasError = GetI2CData(errorFlagAddress, deviceNo, 1, out readData) && readData[0] != 0x0;

            if (hasError)
            {
                // 设置休眠时间：如果剩余重试次数小于等于 2，休眠1500毫秒；否则休眠50毫秒
                int sleepTime = (maxRetries - retryCount <= 2) ? 1500 : 50;
                Thread.Sleep(sleepTime); // 等待设定时间
                retryCount++; // 增加重试计数
            }
            else
            {
                // 如果没有错误，退出循环
                return false; // 返回 false 表示没有错误
            }
        }

        return true; // 返回 true 表示达到最大重试次数
    }



    /// <summary>
    /// 等待缓冲区准备就绪
    /// </summary>
    /// <param name="subB">等待标志的地址</param>
    /// <param name="deviceNo">设备编号</param>
    private bool WaitForBufferReady(uint subB, byte deviceNo)
    {
        DateTime startTime = DateTime.Now;
        byte[] readData;

        do
        {
            if (_isCancelled) return false;
            if ((DateTime.Now - startTime).TotalSeconds > 10)
            {
                OnMsgProcessed?.Invoke($"等待{subB:X}超时  {(DateTime.Now - startTime).TotalSeconds }秒");
                _isCancelled = true;
                return false;
            }
            Thread.Sleep(10);
        } while (GetI2CData(subB, deviceNo, 1, out readData) && (readData[0] != 0x6C || readData[0] != 0xC3));

        return !_isCancelled;
    }

    /// <summary>
    /// 等待数据处理完成
    /// </summary>
    /// <param name="waitAddress">状态标志寄存器地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <returns>是否成功完成处理</returns>
    private bool WaitForDataProcessingCompletion(uint waitAddress, byte deviceNo)
    {
        const int TIMEOUT_SECONDS = 15;
        DateTime start = DateTime.Now;
        byte[] readData;

        while (!_isCancelled)
        {
            // 超时检查（最长等待15秒）
            if ((DateTime.Now - start).TotalSeconds > TIMEOUT_SECONDS)
            {
                OnMsgProcessed?.Invoke($"处理超时 [地址:0x{waitAddress:X}]");
                return false;
            }

            // 读取处理状态（0x00表示处理完成）
            if (GetI2CData(waitAddress, deviceNo, 1, out readData) && readData[0] == 0x00)
                return true;

            Thread.Sleep(15); // 适度延时
        }
        return false; // 被用户取消
    }


    public List<uint> GetAddressData(uint address)
    {
        return new List<uint>
            {
                (byte)((address >> 24) & 0xff),
                (byte)((address >> 16) & 0xff),
                (byte)((address >> 8) & 0xff),
                (byte)(address & 0xff)
            };
    }

    /// <summary>
    /// 检查设备是否存在
    /// </summary>
    /// <param name="deviceIndex"></param>
    /// <returns></returns>
    public bool IsDevicePresent(uint deviceIndex)
    {
        IntPtr namePtr = USBIOXdll.USBIO_GetDeviceName(deviceIndex);

        // 双重验证机制
        bool devicePresent = namePtr != IntPtr.Zero;

        if (devicePresent)
        {
            // 附加验证：检查设备名称有效性
            try
            {
                string deviceName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(namePtr);
                devicePresent = !string.IsNullOrWhiteSpace(deviceName);
            }
            catch
            {
                devicePresent = false;
            }
        }

        return devicePresent;
    }



    /// <summary>
    /// crc 全局变量
    /// </summary>
    static UInt16[] crc16_table ={
          0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
          0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
          0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
          0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
          0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
          0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
          0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
          0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
          0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
          0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
          0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
          0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
          0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
          0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
          0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
          0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
          0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
          0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
          0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
          0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
          0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
          0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
          0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
          0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
          0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
          0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
          0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
          0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
          0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
          0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
          0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
          0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
          };


    static UInt16 XchipCrcCheck16(UInt16 Input, byte[] data)
    {
        UInt16 crc_reg = Input;
        for (int i = 0; i < data.Count(); i++)
        {
            var tempCount = (crc_reg ^ data[i]) & 0xff;
            crc_reg = Convert.ToUInt16((crc_reg >> 8) ^ crc16_table[tempCount]);
        }
        return Convert.ToUInt16(crc_reg & 0xFFFF);
    }


    #region 全新I2C发送方式调用

    /// <summary>
    /// 发送数据到硬件缓冲区（完整实现）
    /// </summary>
    /// <param name="parsedData">解析后的固件数据块</param>
    /// <param name="startAddress">数据写入起始地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <param name="waitFlagAddress">等待标志寄存器地址</param>
    /// <param name="crcErrorAddress">CRC错误标志寄存器地址</param>
    /// <param name="spiErrorAddress">SPI错误标志寄存器地址</param>
    /// <param name="crcWriteAddress">CRC值写入地址</param>
    /// <param name="startAddressCommand">目标起始地址命令寄存器</param>
    /// <param name="expectedReady">缓冲区就绪期望值</param>
    /// <param name="triggerValue">缓冲区处理触发值</param>
    /// <param name="crcReady">CRC正常状态值</param>
    /// <param name="spiReady">SPI正常状态值</param>
    public void SendDataToBuffer(
     ParsedData parsedData,          // 当前要发送的数据块
     ParsedData lastSentData,        // 上一次发送的数据块（用于错误处理）
     uint startAddress,              // 数据写入起始地址
     byte deviceNo,                  // I2C设备编号
     uint waitFlagAddress,           // 等待标志地址
     uint crcErrorAddress,           // CRC错误标志地址
     uint spiErrorAddress,           // SPI错误标志地址
     uint crcWriteAddress,           // CRC写入地址
     uint startAddressCommand,       // 起始地址命令寄存器
     byte expectedReady,             // 就绪期望值
     byte triggerValue,              // 触发值
     byte crcReady,                  // CRC正常状态值
     byte spiReady,                  // SPI正常状态值
     int bufferType)                 // 0 = A区, 1 = B区
    {
        /*********************** 步骤1: 等待缓冲区准备就绪 ***********************/
        if (!WaitForBufferReady(waitFlagAddress, deviceNo, expectedReady))
        {
            OnMsgProcessed?.Invoke($"错误: 缓冲区准备超时 [地址:0x{waitFlagAddress:X}]");
            return;
        }

        /*********************** 步骤2: 检查错误标志 ***********************/
        bool hasCrcError = CheckErrorFlag(crcErrorAddress, deviceNo, crcReady);
        bool hasSpiError = CheckErrorFlag(spiErrorAddress, deviceNo, spiReady);

        // 如果有错误且存在上一次发送的数据块，则进行重试
        if (!_isCancelled && (hasCrcError || hasSpiError) && lastSentData != null)
        {
            // 错误处理流程 - 重发上一次的数据块
            HandleTransmissionError(
                lastSentData,            // 重发上一次的数据块
                startAddress,            // 使用当前缓冲区的起始地址
                deviceNo,
                startAddressCommand,
                crcWriteAddress,
                waitFlagAddress,
                triggerValue,
                hasCrcError,
                hasSpiError,
                crcErrorAddress,
                spiErrorAddress,
                expectedReady,
                crcReady,
                spiReady
            );
        }

        /*********************** 步骤3: 发送目标起始地址到命令寄存器 ***********************/
        // 将32位地址拆分为4字节列表（大端序）
        List<uint> addressData = GetAddressData(parsedData.address);

        if (_isCancelled || !SendI2CData(startAddressCommand, addressData, deviceNo))
        {
            OnMsgProcessed?.Invoke($"错误: 无法发送起始地址 [地址:0x{startAddressCommand:X}]");
            return;
        }

        /*********************** 步骤4: 分块发送固件数据 ***********************/
        if (!SendPacketsWithCheck(parsedData, startAddress, deviceNo))
        {
            OnMsgProcessed?.Invoke($"错误: 数据发送失败 [起始地址:0x{startAddress:X}]");
            return;
        }

        /*********************** 步骤5: 发送CRC校验值 ***********************/
        // 准备CRC数据（2字节）
        List<uint> crcData = new List<uint> { parsedData.crc[0], parsedData.crc[1] };

        if (!SendI2CData(crcWriteAddress, crcData, deviceNo))
        {
            OnMsgProcessed?.Invoke($"错误: CRC发送失败 [地址:0x{crcWriteAddress:X}]");
            return;
        }

        /*********************** 步骤6: 触发缓冲区处理 ***********************/
        if (!SendI2CData(waitFlagAddress, new List<uint> { triggerValue }, deviceNo))
        {
            OnMsgProcessed?.Invoke($"错误: 无法触发处理 [地址:0x{waitFlagAddress:X}]");
            return;
        }

        OnMsgProcessed?.Invoke($"数据块处理完成 [地址:0x{parsedData.address:X}]");

    }

    /// <summary>
    /// 等待缓冲区准备就绪
    /// </summary>
    /// <param name="waitAddress">等待标志寄存器地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <param name="expectedReady">期望的就绪状态值</param>
    /// <returns>是否成功等到就绪状态</returns>
    private bool WaitForBufferReady(uint waitAddress, byte deviceNo, byte expectedReady)
    {
        const int TIMEOUT_SECONDS = 10;
        DateTime start = DateTime.Now;
        byte[] readData;

        while (!_isCancelled)
        {
            // 超时检查（最长等待10秒）
            if ((DateTime.Now - start).TotalSeconds > TIMEOUT_SECONDS)
            {
                OnMsgProcessed?.Invoke($"等待超时 [地址:0x{waitAddress:X}] 期望值:0x{expectedReady:X}");
                return false;
            }

            // 读取当前状态值
            if (GetI2CData(waitAddress, deviceNo, 1, out readData))
            {
                // 检查是否达到期望的就绪状态
                if (readData[0] == expectedReady)
                    return true;
            }

            Thread.Sleep(10); // 避免CPU忙等待，减少资源占用
        }
        return false;
    }

    /// <summary>
    /// 检查错误标志状态
    /// </summary>
    /// <param name="errorAddress">错误标志寄存器地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <returns>true表示存在错误，false表示正常</returns>
    private bool CheckErrorFlag(uint errorAddress, byte deviceNo, byte expectedReady)
    {
        byte[] readData;
        if (GetI2CData(errorAddress, deviceNo, 1, out readData))
        {
            // 等于0值表示正确
            return (readData[0] == expectedReady);
        }
        return true; // 读取失败视为错误
    }

    /// <summary>
    /// 错误处理流程（带重试机制）
    /// </summary>
    /// <param name="parsedData">当前处理的数据块</param>
    /// <param name="startAddress">数据写入起始地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <param name="startAddressCommand">目标起始地址命令寄存器</param>
    /// <param name="crcWriteAddress">CRC值写入地址</param>
    /// <param name="waitFlagAddress">等待标志寄存器地址</param>
    /// <param name="triggerValue">缓冲区触发值</param>
    /// <param name="hasCrcError">是否存在CRC错误</param>
    /// <param name="hasSpiError">是否存在SPI错误</param>
    /// <param name="crcErrorAddress">CRC错误标志寄存器地址</param>
    /// <param name="spiErrorAddress">SPI错误标志寄存器地址</param>
    private void HandleTransmissionError(
        ParsedData parsedData,
        uint startAddress,
        byte deviceNo,
        uint startAddressCommand,
        uint crcWriteAddress,
        uint waitFlagAddress,
        byte triggerValue,
        bool hasCrcError,
        bool hasSpiError,
        uint crcErrorAddress,
        uint spiErrorAddress,
        byte expectedReady,       // 就绪期望值
        byte crcReady,
        byte spiReady)
    {
        StringBuilder log = new StringBuilder();
        log.AppendLine($"检测到传输错误: ");
        log.AppendLine($"CRC错误: {hasCrcError}, SPI错误: {hasSpiError}");
        log.AppendLine($"尝试重传数据块 [地址: 0x{parsedData.address:X}]");

        // 最大重试次数3次
        for (int retry = 0; retry < 3 && !_isCancelled; retry++)
        {
            log.AppendLine($"重试 #{retry + 1}");

            //// 重置错误标志（仅重置实际存在的错误类型）
            if (hasCrcError)
                SendI2CData(crcErrorAddress, new List<uint> { 0x0 }, deviceNo);

            if (hasSpiError)
                SendI2CData(spiErrorAddress, new List<uint> { 0x0 }, deviceNo);

            // 重发目标起始地址
            SendI2CData(startAddressCommand, GetAddressData(parsedData.address), deviceNo);

            // 重发数据包
            SendPacketsWithCheck(parsedData, startAddress, deviceNo);

            // 重发CRC校验值
            SendI2CData(crcWriteAddress, new List<uint> { parsedData.crc[0], parsedData.crc[1] }, deviceNo);

            // 重新触发处理
            SendI2CData(waitFlagAddress, new List<uint> { triggerValue }, deviceNo);

            // 等待操作完成
            if (WaitForDataProcessingCompletion(waitFlagAddress, deviceNo, expectedReady))
            {
                // 重新检查错误状态
                hasCrcError = CheckErrorFlag(crcErrorAddress, deviceNo, crcReady);
                hasSpiError = CheckErrorFlag(spiErrorAddress, deviceNo, spiReady);

                // 错误已解决则退出重试
                if (!hasCrcError && !hasSpiError)
                {
                    log.AppendLine("重试成功，错误已解决");
                    break;
                }
            }

            // 递增延时策略：300ms, 600ms, 900ms
            Thread.Sleep(300 * (retry + 1));
        }

        OnMsgProcessed?.Invoke(log.ToString());
    }
    /// <summary>
    /// 等待数据处理完成
    /// </summary>
    /// <param name="waitAddress">状态标志寄存器地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <returns>是否成功完成处理</returns>
    private bool WaitForDataProcessingCompletion(uint waitAddress, byte deviceNo, byte expectedReady)
    {
        const int TIMEOUT_SECONDS = 15;
        DateTime start = DateTime.Now;
        byte[] readData;

        while (!_isCancelled)
        {
            // 超时检查（最长等待15秒）
            if ((DateTime.Now - start).TotalSeconds > TIMEOUT_SECONDS)
            {
                OnMsgProcessed?.Invoke($"处理超时 [地址:0x{waitAddress:X}]");
                return false;
            }

            // 读取处理状态（0x00表示处理完成）
            if (GetI2CData(waitAddress, deviceNo, 1, out readData) && readData[0] == expectedReady)
                return true;

            Thread.Sleep(15);
        }
        return false;
    }

    /// <summary>
    /// 分块发送数据包（带取消检查）
    /// </summary>
    /// <param name="data">要发送的数据块</param>
    /// <param name="startAddress">起始地址</param>
    /// <param name="deviceNo">I2C设备编号</param>
    /// <returns>是否全部发送成功</returns>
    private bool SendPacketsWithCheck(ParsedData data, uint startAddress, byte deviceNo)
    {
        // 计算总包数（每包SegmentSize字节）
        int totalPackets = (int)Math.Ceiling((double)data.values.Count / SegmentSize);

        for (int j = 0; j < totalPackets && !_isCancelled; j++)
        {
            // 获取当前数据包
            var segment = data.values.Skip(j * SegmentSize).Take(SegmentSize).ToList();

            // 计算当前包地址 = 基地址 + 偏移量
            uint packetAddress = startAddress + (uint)(j * SegmentSize);

            // 发送数据包
            if (!SendI2CData(packetAddress, segment, deviceNo))
                return false;
        }
        return !_isCancelled; // 全部发送完成且未被取消
    }

    #endregion
}

